define([
    'js/resolve',
    'zrender',
    'jquery-ui.rotatable'
], function(resolve, zrender) {
    angular.module('app.zrender', [])
        .directive('zrender', zrenderDirective)
        .run(function($templateCache) {
            $templateCache.put('templates/extendbar/zrender.html',
                '<div class="btn-group">' +
                '  <button class="btn btn-default" title="画笔"><i class="fa fa-pencil"></i></button>' +
                '  <div class="btn-group" title="画笔">' +
                '    <combobox style="width:94px" ng-model="extendbar.shape.value"' +
                '        options="extendbar.shape.options"></combobox>' +
                '  </div>' +
                '  <button class="btn btn-default" title="线条"><i class="fa fa-magic"></i></button>' +
                '  <div class="btn-group" title="线条样式">' +
                '    <combobox style="width:81px" ng-model="extendbar.lineStyle.value"' +
                '        options="extendbar.lineStyle.options" on-selected="extendbar.lineStyle.click"></combobox>' +
                '  </div>' +
                '  <div class="btn-group" title="线条粗细">' +
                '    <combobox style="width:65px" ng-model="extendbar.lineSize.value"' +
                '        options="extendbar.lineSize.options" on-selected="extendbar.lineSize.click"></combobox>' +
                '  </div>' +
                '  <colorpicker position="\'right\'" icon="\'fa-square-o\'" on-selected="extendbar.color.click"' +
                '      color-tips="\'图形颜色\'" forecolor-tips="\'线条色\'" backcolor-tips="\'填充色\'"' +
                '      forecolor="extendbar.color.line" backcolor="extendbar.color.fill"></colorpicker>' +
                '  <colorpicker position="\'right\'" icon="\'fa-font\'" on-selected="extendbar.fontColor.click"' +
                '      color-tips="\'字体颜色\'" forecolor="extendbar.fontColor.fore" backcolor="extendbar.fontColor.back"></colorpicker>' +
                '  <imageupload on-selected="extendbar.image.click"></imageupload>' +
                '  <button class="btn btn-default" title="缩放比例" ng-click="extendbar.aspectRatio.click()">' +
                '    <i class="fa" ng-class="{\'fa-toggle-on\':extendbar.aspectRatio.value,\'fa-toggle-off\':!extendbar.aspectRatio.value}"></i>' +
                '  </button>' +
                '</div>');
        });

    function zrenderDirective($rootScope, $compile, $timeout, $templateCache, _prettier) {
        var canvasIdOffset = 0;
        return resolve({
            restrict: 'E',
            replace: true,
            templateUrl: 'js/templates/zrender.html',
            scope: {
                file: '=',
                context: '=',
                onChanged: '<'
            },
            compile: function() {
                var toolscope = $rootScope.$new(true);
                toolscope.extendbar = {
                    'shape': {
                        value: 'Polyline',
                        options: [{
                            value: 'Polyline',
                            label: '路径'
                        }, {
                            value: 'Line',
                            label: '线段'
                        }, {
                            value: '-'
                        }, {
                            value: 'Arc',
                            label: '圆弧'
                        }, {
                            value: 'Sector',
                            label: '扇形'
                        }, {
                            value: 'Circle',
                            label: '圆'
                        }, {
                            value: 'Ellipse',
                            label: '椭圆'
                        }, {
                            value: '-'
                        }, {
                            value: 'Isogon3',
                            label: '三角形'
                        }, {
                            value: 'Rect',
                            label: '矩形'
                        }, {
                            value: 'Isogon6',
                            label: '六边形'
                        }, {
                            value: 'Droplet',
                            label: '水滴'
                        }, {
                            value: 'Heart',
                            label: '心形'
                        }, {
                            value: 'Star',
                            label: '五角星'
                        }, {
                            value: '-'
                        }, {
                            value: 'Text',
                            label: '文字'
                        }]
                    },
                    'image': { click: null },
                    'color': {
                        line: 'rgb(0, 0, 0)',
                        fill: 'rgba(0, 0, 0, 0)',
                        click: null
                    },
                    'lineStyle': {
                        value: 'solid',
                        options: [{
                            value: 'solid',
                            label: '实线'
                        }, {
                            value: 'dash',
                            label: '虚线'
                        }],
                        click: null
                    },
                    'lineSize': {
                        value: '1',
                        options: [{
                            value: '1',
                            label: '细'
                        }, {
                            value: '2',
                            label: '中'
                        }, {
                            value: '4',
                            label: '粗'
                        }],
                        click: null
                    },
                    'fontColor': {
                        fore: 'rgb(0, 0, 0)',
                        back: 'rgba(0, 0, 0, 0)',
                        click: null
                    },
                    'aspectRatio': {
                        value: false,
                        click: function() {
                            this.value = !this.value;
                            if (typeof(this.change) === 'function') {
                                this.change(this.value);
                            }
                        }
                    }
                };
                var template = $templateCache.get('templates/extendbar/zrender.html');
                var extendbar = jQuery($compile(template)(toolscope));
                extendbar.css('display', 'none');
                extendbar.appendTo(jQuery('.extendbar'));

                const shapeHandlers = {
                    'Polyline': {
                        init: function(x0, y0) {
                            this.attr('shape', {
                                points: [[x0, y0]],
                                smooth: 0.7
                            });
                        },
                        draw: function(x, y) {
                            var points = this.shape.points;
                            points.push([x, y]);
                            this.attr('shape', {
                                points: points
                            });
                        }
                    },
                    'Line': {
                        init: function(x0, y0) {
                            this.attr('shape', {
                                x1: x0, y1: y0, x2: x0, y2: y0
                            });
                        },
                        draw: function(x, y, x0, y0) {
                            this.attr('shape', {
                                x2: x, y2: y
                            });
                        }
                    },
                    'Arc': {
                        init: function(x0, y0) {
                            this.attr('shape', {
                                cx: x0, cy: y0,
                                endAngle: Math.PI,
                                clockwise: false
                            });
                        },
                        draw: function(x, y, x0, y0) {
                            this.attr('shape', {
                                r: Math.max(Math.abs(x - x0), Math.abs(y - y0))
                            });
                        }
                    },
                    'Rect': {
                        init: function(x0, y0) {
                            this.attr('shape', {
                                x: x0, y: y0
                            });
                        },
                        draw: function(x, y, x0, y0) {
                            this.attr('shape', {
                                x: Math.min(x, x0), y: Math.min(y, y0),
                                width: Math.abs(x - x0),
                                height: Math.abs(y - y0)
                            });
                        }
                    },
                    'Circle': {
                        init: function(x0, y0) {
                            this.attr('shape', {
                                cx: x0, cy: y0
                            });
                        },
                        draw: function(x, y, x0, y0) {
                            this.attr('shape', {
                                r: Math.max(Math.abs(x - x0), Math.abs(y - y0))
                            });
                        }
                    },
                    'Ellipse': {
                        init: function(x0, y0) {
                            this.attr('shape', {
                                cx: x0, cy: y0
                            });
                        },
                        draw: function(x, y, x0, y0) {
                            this.attr('shape', {
                                rx: Math.abs(x - x0), ry: Math.abs(y - y0)
                            });
                        }
                    },
                    'Isogon': function(n) {
                        return {
                            init: function(x0, y0) {
                                this.attr('shape', {
                                    x: x0, y: y0, n: n
                                });
                            },
                            draw: function(x, y, x0, y0) {
                                this.attr('shape', {
                                    r: Math.max(Math.abs(x - x0), Math.abs(y - y0))
                                });
                            }
                        }
                    },
                    'Star': {
                        init: function(x0, y0) {
                            this.attr('shape', {
                                cx: x0, cy: y0, n: 5
                            });
                        },
                        draw: function(x, y, x0, y0) {
                            this.attr('shape', {
                                r: Math.max(Math.abs(x - x0), Math.abs(y - y0))
                            });
                        }
                    },
                    'Droplet': {
                        init: function(x0, y0) {
                            this.attr('shape', {
                                cx: x0, cy: y0
                            });
                        },
                        draw: function(x, y, x0, y0) {
                            this.attr('shape', {
                                width: Math.abs(x - x0),
                                height: Math.abs(y - y0)
                            });
                        }
                    },
                    'Heart': {
                        init: function(x0, y0) {
                            this.attr('shape', {
                                cx: x0, cy: y0
                            });
                        },
                        draw: function(x, y, x0, y0) {
                            this.attr('shape', {
                                width: Math.abs(x - x0),
                                height: Math.abs(y - y0)*2 - Math.abs(x - x0)/2
                            });
                        }
                    },
                    'Text': {
                        init: function(x0, y0, context, element, shapeGroup) {
                            var _this = this;
                            _this.attr('position', [x0 + 4, y0 + 7]);
                            jQuery('<div contenteditable="true"></div>')
                            .css({
                                'position': 'absolute',
                                'left': x0 + 'px',
                                'top': y0 + 'px',
                                'padding': '4px',
                                'min-width': '1px',
                                'font-family': 'Segoe UI, Roboto, Ubuntu, sans-serif',
                                'font-size': '16px',
                                'color': (toolscope.extendbar.fontColor.fore || '#333'),
                                'white-space': 'nowrap',
                                'outline': 'rgb(67, 149, 255) dashed 1px'
                            })
                            .on('blur', function() {
                                if (/[^\s]+/.test(jQuery(this).text())) {
                                    var fontColor = toolscope.extendbar.fontColor;
                                    _this.attr('style', {
                                        fill: (fontColor.fore || 'none'),
                                        stroke: (fontColor.back || 'none'),
                                        text: _.map(this.childNodes, function(node) {
                                            return jQuery(node).text();
                                        }).join('\n'),
                                        fontFamily: 'Segoe UI, Roboto, Ubuntu, sans-serif',
                                        fontSize: 16,
                                        fontWeight: 'normal'
                                    });
                                    context.onChanged();
                                } else {
                                    shapeGroup.remove(_this);
                                }
                                jQuery(this).remove();
                            })
                            .appendTo(element.find('.handler'))
                            .focus();
                        }
                    }
                };
                shapeHandlers['Sector'] = shapeHandlers['Arc'];
                shapeHandlers['Isogon3'] = shapeHandlers['Isogon'](3);
                shapeHandlers['Isogon6'] = shapeHandlers['Isogon'](6);

                function getInstance(shape, context, element, options) {
                    var _options = options;
                    if (!_options) {
                        var fillColor = toolscope.extendbar.color.fill;
                        var lineColor = toolscope.extendbar.color.line;
                        _options = {
                            zlevel: context.zlevel.max,
                            shape: {},
                            style: {
                                fill: (/rgba\((\d+, ?)+0\)/.test(fillColor) ? 'none' : fillColor),
                                stroke: (lineColor || 'none'),
                                lineWidth: parseInt(toolscope.extendbar.lineSize.value),
                                strokeNoScale: true,
                                lineDash: (toolscope.extendbar.lineStyle.value == 'dash' ? [6, 4] : null)
                            }
                        };
                    }
                    return new zrender[shape](_options).on('mousedown', function(event) {
                        var _this = this;
                        context.selected = _this;
                        var boxRect = _this.getBoundingRect();
                        element.find('.handler').children().hide();
                        if (jQuery('#ui-' + context.id + '-' + _this.id).length == 0) {
                            var tooltip = (function() {
                                var _width, _height, _degrees = 0;
                                var _dom = jQuery('<div class="ui-tooltip"></div>');
                                var _setText = function(width, height, degrees) {
                                    _width = Math.round(width || _width);
                                    _height = Math.round(height || _height);
                                    _degrees = Math.round(degrees || _degrees);
                                    _dom.text(_width + 'x' + _height + ',' + _degrees + 'deg');
                                };
                                _setText(boxRect.width * _this.scaleX, boxRect.height * _this.scaleY,
                                        -_this.rotation * 180 / Math.PI);
                                return {
                                    dom: _dom,
                                    resize: function(width, height) {
                                        _setText(width, height);
                                    },
                                    rotate: function(degrees) {
                                        _setText(null, null, degrees);
                                    }
                                };
                            })();
                            jQuery('<div id="ui-' + context.id + '-' + _this.id + '"></div>')
                                .css({
                                    //'position': 'absolute',
                                    'left': (boxRect.x + boxRect.width*(1 - _this.scaleX)/2 + _this.x) + 'px',
                                    'top': (boxRect.y + boxRect.height*(1 - _this.scaleY)/2 + _this.y) + 'px',
                                    //'margin': '-1px 0 0 -1px',
                                    'width': (boxRect.width * _this.scaleX) + 'px',
                                    'height': (boxRect.height * _this.scaleY) + 'px',
                                    'border': '1px dashed rgb(67, 149, 255)',
                                    'background-color': 'rgba(255, 250, 144, 0.05)',
                                    'cursor': 'move'
                                })
                                .draggable({
                                    drag: function(event, ui) {
                                        boxRect = _this.getBoundingRect();
                                        _this.attr('position', [
                                            ui.position.left - boxRect.x - boxRect.width*(1 - _this.scaleX)/2,
                                            ui.position.top - boxRect.y - boxRect.height*(1 - _this.scaleY)/2
                                        ]);
                                    },
                                    stop: function(event, ui) {
                                        context.onChanged();
                                    }
                                })
                                .resizable({
                                    minWidth: 4,
                                    minHeight: 4,
                                    aspectRatio: toolscope.extendbar.aspectRatio.value,
                                    handles: 'n, e, s, w, ne, se, sw, nw',
                                    start: function(event, ui) {
                                        boxRect = _this.getBoundingRect();
                                        _this.attr('origin', [
                                            boxRect.x + boxRect.width/2,
                                            boxRect.y + boxRect.height/2
                                        ]);
                                    },
                                    resize: function(event, ui) {
                                        var _width = ui.element.outerWidth(),
                                            _height = ui.element.outerHeight();
                                        boxRect = _this.getBoundingRect();
                                        _this.attr({
                                            'scale': [
                                                _width/boxRect.width,
                                                _height/boxRect.height
                                            ],
                                            'position': [
                                                ui.position.left - boxRect.x + (_width - boxRect.width)/2,
                                                ui.position.top - boxRect.y + (_height - boxRect.height)/2
                                            ]
                                        });
                                        tooltip.resize(_width, _height);
                                    },
                                    stop: function(event, ui) {
                                        context.onChanged();
                                    }
                                })
                                .rotatable({
                                    radians: -_this.rotation,
                                    wheelRotate: false,
                                    start: function(event, ui) {
                                        boxRect = _this.getBoundingRect();
                                        _this.attr('origin', [
                                            boxRect.x + boxRect.width/2,
                                            boxRect.y + boxRect.height/2
                                        ]);
                                    },
                                    rotate: function(event, ui) {
                                        _this.attr('rotation', -ui.angle.current);
                                        tooltip.rotate(ui.angle.degrees);
                                    },
                                    stop: function(event, ui) {
                                        context.onChanged();
                                    }
                                })
                                .on('dblclick', function() {
                                    jQuery(this).hide();
                                    context.selected = null;
                                })
                                .append(tooltip.dom)
                                .appendTo(element.find('.handler'));
                        } else {
                            jQuery('#ui-' + context.id + '-' + _this.id)
                                .resizable('option', 'aspectRatio', toolscope.extendbar.aspectRatio.value)
                                .show();
                        }
                        event.stop();
                    });
                }

                function loadShapeData(data, context, element, stage) {
                    _.each(JSON.parse(data || '[]'), function(option) {
                        if (option.zlevel < context.zlevel.min) {
                            context.zlevel.min = option.zlevel;
                        }
                        if (option.zlevel > context.zlevel.max) {
                            context.zlevel.max = option.zlevel;
                        }
                        var shape = getInstance(option.type, context, element, {
                            shape: option.shape,
                            style: option.style,
                            position: option.position,
                            zlevel: option.zlevel
                        });
                        stage.add(shape);
                        var boxRect = shape.getBoundingRect();
                        shape.attr({
                            'origin': [
                                boxRect.x + boxRect.width/2,
                                boxRect.y + boxRect.height/2
                            ],
                            'scale': option.scale,
                            'rotation': option.rotation
                        });
                    });
                }

                return {
                    post: function(scope, element) {
                        var context = { init: true, reload: false, selected: null };
                        context.id = 'zr' + (canvasIdOffset++);
                        context.zlevel = { min: 0, max: 1 };
                        context.onChanged = function() {
                            if (!context.init) {
                                $timeout(function() {
                                    scope.file.changed = true;
                                    scope.context.navbar['file']['save'].enabled = true;
                                });
                                if (typeof(scope.onChanged) === 'function') {
                                    scope.onChanged();
                                }
                            }
                        };
                        // editor
                        var editor = zrender.init(element.find('.canvas')[0], {
                            width: 'auto',
                            height: 'auto',
                            renderer: 'svg'
                        });

                        element.bind('mousedown mouseup', function(event) {
                            element.find('textarea').css({
                                'left': event.offsetX + 'px',
                                'top': event.offsetY + 'px'
                            }).focus();
                        });
                        element.find('textarea').bind('keydown', function(event) {
                            if (context.selected) {
                                var move = { left: 0, top: 0 };
                                if (event.keyCode == 46) {// delete
                                    event.preventDefault();
                                    scope.editor.remove.click();
                                } else if (event.keyCode == 38) {// up
                                    event.preventDefault();
                                    move.top = -1;
                                } else if(event.keyCode == 40) {// down
                                    event.preventDefault();
                                    move.top = 1;
                                } else if (event.keyCode == 37) {// left
                                    event.preventDefault();
                                    move.left = -1;
                                } else if (event.keyCode == 39) {// right
                                    event.preventDefault();
                                    move.left = 1;
                                }
                                if (move.left || move.top) {
                                    var target = jQuery('#ui-' + context.id + '-' + context.selected.id);
                                    var left = parseFloat(target.css('left')) + move.left,
                                        top = parseFloat(target.css('top')) + move.top;
                                    target.css({
                                        'left': left + 'px',
                                        'top': top + 'px'
                                    }).draggable('option', 'drag')(event, {
                                        position: { left: left, top: top }
                                    });
                                }
                            } else if (event.ctrlKey && event.keyCode == 83) {// ctrl+s
                                event.preventDefault();
                                if (scope.file.changed) {
                                    scope.context.navbar['file']['save'].click();
                                }
                            }
                        });

                        var shapeGroup = new zrender.Group({
                            position: [0, 0]
                        });
                        editor.add(shapeGroup);

                        (function(handlers) {
                            var _this, _x0, _y0, _x, _y;
                            var moveable = false;
                            var handler = null;
                            element.find('.canvas')
                            .bind('click', function(event) {
                                if (toolscope.extendbar.shape.value == 'Text') {
                                    _this = getInstance('Text', context, element);
                                    _x0 = event.offsetX;
                                    _y0 = event.offsetY;
                                    shapeGroup.add(_this);
                                    handlers['Text'].init.call(_this, _x0, _y0, context, element, shapeGroup);
                                }
                            })
                            .bind('mousedown', function(event) {
                                _this = null;
                                _x0 = event.offsetX;
                                _y0 = event.offsetY;
                                moveable = true;
                                context.selected = null;
                                element.find('.handler').children().hide();
                            })
                            .bind('mousemove', function(event) {
                                if (moveable && toolscope.extendbar.shape.value != 'Text') {
                                    _x = event.offsetX;
                                    _y = event.offsetY;
                                    handler = handlers[toolscope.extendbar.shape.value];
                                    if (_this) {
                                        handler.draw.call(_this, _x, _y, _x0, _y0, element);
                                    } else {
                                        _this = getInstance(toolscope.extendbar.shape.value.replace(/[^A-Za-z]/g, ''),
                                                context, element);
                                        shapeGroup.add(_this);
                                        handler.init.call(_this, _x0, _y0, element);
                                        setTimeout(function() {
                                            if (_x == _x0 && _y == _y0) {
                                                shapeGroup.remove(_this);
                                                _this = null;
                                            } else {
                                                context.onChanged();
                                            }
                                        }, 300);
                                    }
                                }
                            })
                            .bind('mouseup', function(event) {
                                if (moveable) {
                                    moveable = false;
                                    if (_this) {
                                        _this.dirty();
                                    }
                                }
                            });
                        })(shapeHandlers);

                        scope.editor = {
                            undo: { click: null },
                            redo: { click: null },
                            cut: { click: null },
                            copy: { click: null },
                            paste: { click: null },
                            level: {
                                enabled: false,
                                click: function(dir) {
                                    var zlevel = context.selected.zlevel;
                                    switch (dir) {
                                    case 'top':
                                        zlevel = context.zlevel.max + 1;
                                        break;
                                    case 'up':
                                        zlevel++;
                                        break;
                                    case 'down':
                                        zlevel--;
                                        break;
                                    case 'bottom':
                                        zlevel = context.zlevel.min - 1;
                                        break;
                                    }
                                    context.selected.attr('zlevel', zlevel);
                                    if (zlevel < context.zlevel.min) {
                                        context.zlevel.min = zlevel;
                                    }
                                    if (zlevel > context.zlevel.max) {
                                        context.zlevel.max = zlevel;
                                    }
                                }
                            },
                            remove: scope.context.navbar['edit']['delete'],
                            clear: {
                                enabled: false,
                                click: function() {
                                    _.each(shapeGroup.children(), function(shape) {
                                        shapeGroup.remove(shape);
                                        editor.remove(shape);
                                    });
                                    element.find('.handler').children().remove();
                                    context.zlevel = { min: 0, max: 0 };
                                    context.selected = null;
                                    context.onChanged();
                                }
                            },
                            save: scope.context.navbar['file']['save']
                        };

                        scope.file.reloader = function(helper, reloaded) {
                            scope.editor.clear.click();
                            context.reload = true;
                            if (reloaded) {
                                loadData(scope.file.data);
                            } else if (scope.file.path) {
                                helper.read(scope.file).then(function(fileObj) {
                                    loadData(fileObj.data);
                                });
                            } else if (scope.file.data) {
                                loadData(scope.file.data);
                            } else {
                                context.init = false;
                                context.reload = false;
                            }
                            $timeout(function() {
                                editor.resize();
                            }, 50);

                            function loadData(data) {
                                loadShapeData(data, context, element, shapeGroup);
                                $timeout(function() {
                                    context.init = false;
                                    context.reload = false;
                                    scope.file.changed = false;
                                    scope.editor['save'].enabled = false;
                                }, 50);
                            }
                        }

                        scope.file.extractor = function() {
                            var data = [];
                            _.each(shapeGroup.children(), function(shape) {
                                data.push({
                                    type: shape.type,
                                    shape: shape.shape,
                                    style: shape.style,
                                    position: shape.position,
                                    scale: shape.scale,
                                    rotation: shape.rotation,
                                    zlevel: shape.zlevel
                                });
                            });
                            scope.file.data = _prettier.format(
                                JSON.stringify(data, function(key, value) {
                                    if (value == null) {
                                        return undefined;
                                    }
                                    if (key == 'type') {
                                        return value.substring(0, 1).toUpperCase() + value.substring(1);
                                    }
                                    return value;
                                }), {
                                    parser: 'json',
                                    printWidth: 80,
                                }
                            );
                        }

                        scope.file.renderer = function(helper) {
                            // editor
                            if (!scope.file.opened) {
                                scope.file.opened = true;
                                scope.file.reloader(helper);
                            }

                            // extendbar
                            extendbar.css('display', '');
                            toolscope.extendbar['image'].click = function(image) {
                                var _image = new Image();
                                _image.onload = function() {
                                    var cursor = element.find('textarea');
                                    var shape = getInstance('Image', context, element, {
                                        style: {
                                            image: image.url,
                                            x: 0, y: 0,
                                            width: _image.width,
                                            height: _image.height
                                        },
                                        position: [
                                            parseFloat(cursor.css('left') || '0'),
                                            parseFloat(cursor.css('top') || '0')
                                        ]
                                    });
                                    shapeGroup.add(shape);
                                    context.onChanged();
                                };
                                _image.src= image.url;
                            };
                            toolscope.extendbar['color'].click = function(lineColor, fillColor) {
                                if (context.selected && context.selected.type != 'text') {
                                    context.selected.attr('style', {
                                        fill: (/rgba\((\d+, ?)+0\)/.test(fillColor) ? 'none' : fillColor),
                                        stroke: (lineColor || 'none')
                                    });
                                    context.onChanged();
                                }
                            };
                            toolscope.extendbar['lineStyle'].click = function(style) {
                                if (context.selected) {
                                    context.selected.attr('style', {
                                        lineDash: (style == 'dash' ? [6, 4] : null)
                                    });
                                    context.onChanged();
                                }
                            };
                            toolscope.extendbar['lineSize'].click = function(size) {
                                if (context.selected) {
                                    context.selected.attr('style', {
                                        lineWidth: parseInt(size)
                                    });
                                    context.onChanged();
                                }
                            };
                            toolscope.extendbar['fontColor'].click = function(forecolor, backcolor) {
                                if (context.selected && context.selected.type == 'text') {
                                    context.selected.attr('style', {
                                        fill: (forecolor || 'none'),
                                        stroke: (backcolor || 'none')
                                    });
                                    context.onChanged();
                                }
                            };
                            toolscope.extendbar['aspectRatio'].change = function(value) {
                                element.find('.ui-resizable').resizable('option', 'aspectRatio', value);
                            };

                            // navbar
                            scope.context.navbar['file']['save'].enabled = scope.file.changed;
                            scope.context.navbar['file']['save'].click = function() {
                                helper.save(scope.file);
                            };
                            scope.context.navbar['edit']['undo'].enabled = false;
                            scope.context.navbar['edit']['redo'].enabled = false;
                            scope.context.navbar['edit']['cut'].enabled = false;
                            scope.context.navbar['edit']['copy'].enabled = false;
                            scope.context.navbar['edit']['paste'].enabled = false;
                            scope.context.navbar['edit']['selectAll'].enabled = false;
                            scope.context.navbar['edit']['delete'].enabled = (context.selected != null);
                            scope.context.navbar['edit']['delete'].click = function() {
                                shapeGroup.remove(context.selected);
                                editor.remove(context.selected);
                                jQuery('#ui-' + context.id + '-' + context.selected.id).remove();
                                context.selected = null;
                                context.onChanged();
                            };
                            scope.context.navbar['edit']['find'].enabled = false;
                            scope.context.navbar['edit']['format'].enabled = false;

                            // statusbar
                            scope.context.statusbar.link = scope.file.path;
                            scope.context.statusbar.statuses = ['可写'];
                        }

                        scope.$watch(function() {
                            return context.selected != null;
                        }, function(selected) {
                            scope.editor['level'].enabled = selected;
                            scope.editor['remove'].enabled = selected;
                        }, true);

                        scope.$on('@resize.all', function(event) {
                            $timeout(function() {
                                editor.resize();
                            }, 50);
                        });

                        // destroy
                        scope.$on('$destroy', function() {
                            editor.dispose();
                        });
                    }
                };
            }
        });
    }
});
